/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * TSPMain.java
 *
 * Created on 22-Apr-2011, 13:24:51
 */
package worldview;

import antcolony.City;
import antcolony.Road;
import antcolony.World;
import antcolony.WorldBuilder;
import java.awt.Point;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;

/**
 *
 * @author ikattey
 */
public class TSPMain extends javax.swing.JFrame {

    List<Point> cityLocations;
    Thread tspThread;
    List<City> bestTour;
    List<CityView> cities;
    HashMap<City, CityView> cityMap;
    WorldBuilder worldBuilder;
    HashMap<Road, CityPair> roadMap;
    List<CityPair> roads;

    /** Creates new form TSPMain */
    public TSPMain() {
        //cityLocations = new ArrayList<Point>();
        cities = new ArrayList<CityView>();
         roads = new ArrayList<CityPair>();
        initComponents();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        pnlDraw = new DrawingArea(this);
        btnStart = new javax.swing.JButton();
        btnStop = new javax.swing.JButton();
        btnClear = new javax.swing.JButton();
        jSeparator1 = new javax.swing.JSeparator();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Travelling Salesman");
        setName("TSP"); // NOI18N
        setResizable(false);

        pnlDraw.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.LOWERED));

        javax.swing.GroupLayout pnlDrawLayout = new javax.swing.GroupLayout(pnlDraw);
        pnlDraw.setLayout(pnlDrawLayout);
        pnlDrawLayout.setHorizontalGroup(
            pnlDrawLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 961, Short.MAX_VALUE)
        );
        pnlDrawLayout.setVerticalGroup(
            pnlDrawLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 489, Short.MAX_VALUE)
        );

        btnStart.setText("Start");
        btnStart.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnStartActionPerformed(evt);
            }
        });

        btnStop.setText("Stop");
        btnStop.setEnabled(false);

        btnClear.setText("Clear");

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addGap(268, 268, 268)
                        .addComponent(btnStart)
                        .addGap(18, 18, 18)
                        .addComponent(btnStop)
                        .addGap(188, 188, 188)
                        .addComponent(btnClear))
                    .addGroup(layout.createSequentialGroup()
                        .addContainerGap()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jSeparator1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 967, Short.MAX_VALUE)
                            .addComponent(pnlDraw, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(pnlDraw, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(btnStop)
                    .addComponent(btnStart)
                    .addComponent(btnClear))
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void btnStartActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnStartActionPerformed
        // TODO add your handling code here:
      //  StopTsp();

        if (cities.size() < 4) {
            JOptionPane.showMessageDialog(this,
                    "At least 4 cities are needed",
                    "Insufficient cities", JOptionPane.ERROR_MESSAGE);
            return;
        }
        btnStop.setEnabled(true);
        btnStart.setEnabled(false);

        tspThread = new Thread(new TSPThread());
        tspThread.start();
    }//GEN-LAST:event_btnStartActionPerformed

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new TSPMain().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnClear;
    private javax.swing.JButton btnStart;
    private javax.swing.JButton btnStop;
    private javax.swing.JSeparator jSeparator1;
    private javax.swing.JPanel pnlDraw;
    // End of variables declaration//GEN-END:variables

    public void addClickPoint(Point point) {
        //cityLocations.add(point);
        CityView cityView = new CityView(point, nameFromLocation(point), new City(nameFromLocation(point)));
        cities.add(cityView);

//        for(CityView city : cities)
//        {
//            System.out.println("C1 :" + cityView.getName() + " C2: " + city.getName());
//            roads.add(new CityPair(cityView, city));
//        }
    }

    private String nameFromLocation(Point location) {
        return location.toString();
    }

    private void StopTsp() {

        if (tspThread != null && tspThread.isAlive()) {
            try {
                tspThread.interrupt();
                tspThread.join();
            } catch (InterruptedException ex) {
                Logger.getLogger(TSPMain.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

    }

    private World constructTSP() {
        worldBuilder = new WorldBuilder();
        cityMap = new HashMap<City, CityView>(cities.size());

        //create road map
        for(int i=0; i<cities.size(); i++)
        {
            for(int j=0; j<cities.size(); j++)
            {
                if(i != j)
                {
                   roads.add(new CityPair(cities.get(i), cities.get(j)));
                   System.out.println("C1 :" + cities.get(i).getName() + " C2: " + cities.get(j).getName());
                }
            }
        }

        for (Iterator iter = cities.iterator(); iter.hasNext();) {
            CityView cityView = (CityView) iter.next();
            cityView.setTspCity(worldBuilder.addCity(cityView.getName()));
            cityMap.put(cityView.getTspCity(), cityView);
        }

        roadMap = new HashMap<Road, CityPair>((int)Math.pow(cities.size(), 2));

        for(CityPair road : roads)
        {
            roadMap.put(worldBuilder.addRoad(CityView.calculateDistance(road.getCityFrom().getLocation(), 
                    road.getCityTo().getLocation()),road.getCityFrom().getTspCity(), road.getCityTo().getTspCity()), road);
        }

        return new World(worldBuilder);

    }

    class TSPThread implements Runnable {
        public void run() {
            World tspWorld = constructTSP();
            bestTour = tspWorld.findTour();
        }
    }
}
